home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / chgpath.arc / CHGPATH.C next >
Encoding:
C/C++ Source or Header  |  1987-04-06  |  10.7 KB  |  433 lines

  1. /*
  2.      Copyright (C) 1987 by Scott Mason, except where noted in the 
  3.        source code,  All Rights Reserved.
  4.  
  5.      Permission is hereby granted for use by non-profit entities only.
  6.      Distribution of this file, CHGPATH.EXE, and/or CHGPATH.DOC in any form
  7.      for a fee is prohibited.
  8.  
  9.      Written by Scott Mason
  10.                 4050 Jay Em Circle
  11.                 Ellicott City, MD  21043
  12.  
  13.      Written using the DeSmet C88 C compiler package, v2.51
  14.   
  15.      Acknowledgement and graditude is hereby given to:
  16.  
  17.          John M Sellens,
  18.                     who wrote the getpath & parse_path functions, and
  19.          Dan Lewis,
  20.                     who wrote the execute_string (and subsequent)
  21.                     functions, obtained from a file called SETVAR.C.
  22.      ------------------------------------------------------------------
  23.      Purpose:  Allows you the make permanent changes to the PATH
  24.                environment string from the DOS command line without
  25.                having to retype the entire PATH command string.
  26.   
  27. */   
  28.  
  29. #include <stdio.h>
  30.  
  31. char newpath[200] = "PATH ";
  32. char *np = newpath;
  33. char *cp;
  34. typedef char *char_ptr;
  35. char *get_path();
  36. char_ptr  *parse_path();
  37. char *copyright  = " Copyright (C) 1987 by Scott Mason, except where noted\n";
  38. char *copyright2 = " in the source code,  All Rights Reserved.\n";
  39.  
  40. main(argc,argv)
  41. int argc;
  42. char **argv;
  43. {
  44.     int i;
  45.  
  46.     if (argc != 2)
  47.         usage();
  48.  
  49.     cp = get_path();        /* get the PATH environment string */
  50.  
  51.     argv++;
  52.     if (**argv == '+')
  53.         addpath(++*argv);
  54.     else if (**argv == '-')
  55.         delpath(++*argv);
  56.     else
  57.         usage();
  58.  
  59. }    /* end main */
  60.  
  61.  
  62. addpath(p)
  63. char *p;
  64. {
  65.  
  66.     strcat(np,cp);   /* concat current path setting onto newpath */
  67.     strcat(np,";");
  68.     strcat(np,p);   /* concat the path to add onto newpath */
  69.     execute_string(np);
  70.     printf("%s\n",np);
  71.  
  72. }    /* end addpath */
  73.  
  74.  
  75. delpath(p)
  76. char *p;
  77. {
  78.     int i, j;
  79.     char_ptr *paths;
  80.     char *s;
  81.  
  82.     s = p;
  83.     while (*s)                /* convert path to delete to upper case */
  84.     {
  85.         if (isalpha(*s))
  86.             *s = toupper(*s);
  87.         s++;
  88.     }
  89.  
  90.     paths = parse_path(cp);
  91.     if (paths != NULL)
  92.     {
  93.         for (i=0; paths[i]!=NULL; i++)
  94.         {                             /* compare with the path to delete */
  95.            if (strlen(p) != (j=strlen(paths[i])) ||  /* beats DeSmet strncmp bug */
  96.                      strncmp(p,paths[i],j)) 
  97.             {
  98.                 strcat(np,paths[i]);         /* if not ==, concat that path onto */
  99.                 strcat(np,";");        /*  the newpath string */
  100.             }
  101.         }
  102.         *(p = rindex(np,';')) = '\0';    /* get rid of that last ; */
  103.         execute_string(np);
  104.         printf("%s\n",np);
  105.     }
  106.     else
  107.         printf("No path is set ...\n");
  108.  
  109. }    /* end delpath */
  110.  
  111.  
  112. usage()
  113. {
  114.     puts("\nUsage:  CHGPATH  +newpath\n");
  115.     puts("            to Add newpath to the current path setting\n");
  116.     puts("        CHGPATH  -oldpath\n");
  117.     puts("            to Remove oldpath from the current path setting\n\n");
  118.     puts("    Where newpath & oldpath must be valid paths.\n\n");
  119.     exit(1);
  120.  
  121. }    /* end usage */
  122.  
  123.  
  124. /**********************************************************************/
  125.  
  126.  
  127. /* The following are two routines to make it easier to access the
  128.    PATH environment variable.  They are written for use with the
  129.    DeSmet C Compiler.  Known portability problems:
  130.  
  131.                 - assembler code embedded in the C code
  132.                 - requires that code segment register (CS) be set to the
  133.                   same value as at program invocation so that the
  134.                   program segment prefix can be located.  This would
  135.                   probably only be a problem if a "large model"
  136.                   compiler is used.
  137.  
  138.         The code is a little kludgy in places but...
  139.         Any suggestions for improvements gratefully accepted.
  140. */
  141.  
  142. /*   Written by John M Sellens, April, 1984
  143.      (c) Copyright 1984 John M Sellens
  144.  
  145. Permission is granted to use, distribute and/or modify this code unless
  146. done for direct commercial profit.  If you find these routines useful,
  147. modest contributions (monetary or otherwise) will be gratefully accepted.
  148. Author's name, address and this notice must be included in any copies.
  149. */
  150.  
  151. char_ptr *parse_path(ps)
  152. char *ps;
  153. {
  154.         /* Takes the path string returned by get_path and  destroys it,
  155.            by inserting NULL's and returning an array of pointers to
  156.            characters that point to locations in the original path
  157.            string.  The pointer after the last pointer into the path
  158.            string is NULL.  If the path string is NULL, then NULL is
  159.            returned.
  160.         */
  161.  
  162.         int i, j, num;
  163.         char_ptr *pa;
  164.  
  165.         if (ps[0] == '\0')      /* no path */
  166.             return(NULL);
  167.  
  168.         /* count the number of semi-colons, add 1 = number of paths */
  169.  
  170.         for (num=1, i=0; ps[i] != '\0'; i++)
  171.             if (ps[i] == ';')
  172.                  num++;
  173.  
  174.         pa = (char_ptr *)malloc(sizeof(char_ptr) * (num+1));
  175.         pa[num] = NULL;
  176.  
  177.         /* now loop through and point to each path */
  178.  
  179.         for (i=j=0; i<num; i++) 
  180.         {
  181.             pa[i] = &ps[j];
  182.             while(ps[j]!=';' && ps[j]!='\0')
  183.                 j++;
  184.             ps[j++] = '\0';
  185.         }
  186.  
  187.         return(pa);
  188. }
  189.  
  190.  
  191.  
  192. char *get_path()
  193. {
  194.         /* Returns a pointer to a string containing the value of
  195.            the environment variable PATH.  E.g. if PATH=A:\;B:\
  196.            the string "A:\;B:\" is returned.  If no PATH is set,
  197.            an empty string is returned.
  198.         */
  199.  
  200.         static int path_seg;
  201.  
  202.         /* these three declarations must be first so that they can be
  203.            referred to by stack address near the end when copying
  204.            the PATH variable */
  205.  
  206.         char *base, *path;
  207.         int siz;
  208.         char *next;
  209.         char env_str[10];       /* leave a little extra space just in case */
  210.         int i, done;
  211.  
  212. #asm
  213.  
  214. ;               determine the segment that the environment starts at
  215. ;               this requires that cs is set to the same value as at
  216. ;               program entry i.e. 100H past the program segment prefix
  217.  
  218.                 push es
  219.                 mov ax,cs
  220.                 sbb ax,10h
  221.                 mov es,ax
  222.                 mov ax,es:[2cH]
  223.                 pop es
  224.                 mov word get_path_path_seg_,ax
  225. #end
  226.  
  227.         /* look for the start of PATH= */
  228.         /* there's always going to be at least one thing in environment */
  229.  
  230.         done = FALSE;
  231.         next = 0;
  232.         env_str[0] = '\0';
  233.         while ((strncmp("PATH=",env_str,5) != 0) && !done) 
  234.         {
  235.             base = next;
  236.  
  237.             /* set DS to path_seg */
  238.  
  239. #asm
  240.             push ds
  241.             mov ds,word get_path_path_seg_
  242.  
  243. #end
  244.  
  245.             if (base[0] == '\0')
  246.                 done = TRUE;    /* no more variables to look at */
  247.  
  248.             else
  249.             {        /* now copy 5 characters into memory */
  250.                 for (i=0; i<5; i++)
  251.                      env_str[i] = base[i];   /* ok since env_str is on stack */
  252.  
  253.                         /* now set next to first character after end of this string */
  254.  
  255.                 while ((next++)[0] != '\0')
  256.                          ;
  257.             }
  258.                 /* reset DS */
  259. #asm
  260.             pop ds
  261. #end
  262.  
  263.         }
  264.         if (done) {     /* no PATH environment variable set */
  265.             path = (char *)malloc(1);
  266.             path[0] = '\0';
  267.         } else {
  268.             siz = next - base - 5;
  269.             path = (char *)malloc(siz);
  270.             base += 5;      /* skip over 'PATH=' */
  271.                          /* copy the PATH string to path */
  272. #asm
  273.             push cx
  274.             push es
  275.             push ds
  276.             mov cx,ds
  277.             mov es,cx
  278.             mov ds,word get_path_path_seg_
  279.             mov si,word [bp-2]      ;base
  280.             mov di,word [bp-4]      ;path
  281.             mov cx,word [bp-6]      ;siz
  282.             rep movsb
  283.             pop ds
  284.             pop es
  285.             pop cx
  286. #end
  287.         }
  288.         return(path);
  289.  
  290. }
  291. /******************************************************************/
  292. /*
  293.     The following little program can set an environment variable
  294.     whose name is the first command line argument, and whose new
  295.     value is the second command line argument.  For example, to
  296.     set environment variable XYZ to a value of HELLO, you would
  297.     run this program using the command SETVAR XYZ HELLO.
  298.  
  299.     The *PURPOSE* of this piece of code is to illustrate an un-
  300.     documented DOS interrupt entry point (2Eh) that will execute
  301.     *ANY* DOS command *WITHOUT* having to load another copy of
  302.     COMMAND.COM.  Not only is it faster, but it is the ONLY way
  303.     to set an environment variable (short of peeking and poking
  304.     around into memory).  You *CAN'T* set an environment variable
  305.     with the command exec("COMMAND.COM", "/CSETXYZ=HELLO") because
  306.     when the second copy of COMMAND.COM is loaded, it gets its
  307.     very own environment (a duplicate of the parent's).  Although
  308.     the SET command WILL modify that duplicate copy, it won't
  309.     modify the parent's!
  310.  
  311.     When I said that interrupt 2Eh can be used to execute *ANY*
  312.     DOS command, I meant just that!  You can leave off the filename
  313.     extension (as you normally do at the command line), and it will
  314.     perform the normal search for COM, EXE, and BAT files to execute,
  315.     or even execute built-in commands as we've seen above.
  316.  
  317.     Enjoy!
  318.  
  319.     Dan Lewis, owner
  320.     Key Software Products
  321.     440 Ninth Avenue
  322.     Menlo Park, CA 94025
  323.     (415) 364-9847
  324.  
  325. */
  326.  
  327. Execute_String(s)
  328. char *s;
  329. {
  330.     long vec22, vec23, vec24 ;
  331.     long Get_Vec() ;
  332.     static char bfr[81];
  333.  
  334.     strcpy(bfr + 1,s) ;
  335.     *bfr = strlen(bfr + 1) ;
  336.     strcat(bfr + 1,"\r") ;
  337.  
  338.     /* preserve cntrl-break, terminate, and critical error vectors */
  339.     vec22 = Get_Vec(0x22) ;
  340.     vec23 = Get_Vec(0x23) ;
  341.     vec24 = Get_Vec(0x24) ;
  342.  
  343.     Release_Memory() ;
  344.     Exec(bfr) ;    /* execute command */
  345.  
  346.     /* reset cntrl-break, terminate, and critical error vectors */
  347.     Set_Vec(0x22,vec22) ;
  348.     Set_Vec(0x23,vec23) ;
  349.     Set_Vec(0x24,vec24) ;
  350.     }
  351.  
  352. Exec(s)
  353. char *s ;
  354. {
  355. #asm
  356.     push    ds
  357.     push    bp
  358.     mov    cs:WORD save_ss,ss
  359.     mov    cs:WORD save_sp,sp
  360.     mov    si,[bp+4]
  361.     int    2Eh
  362.     mov    ss,cs:WORD save_ss
  363.     mov    sp,cs:WORD save_sp
  364.     pop    bp
  365.     pop    ds
  366.     jmp    Rtn
  367.  
  368. save_ss:dw    0
  369. save_sp:dw    0
  370. save_ds:dw    0
  371. save_bp:dw    0
  372.  
  373. Rtn:
  374. #end
  375. }
  376.  
  377.  
  378. Release_Memory()
  379. {
  380.     if (Release())
  381.     {
  382.         puts("Release Memory Failure\n") ;
  383.         exit(1) ;
  384.     }
  385. }
  386.  
  387.  
  388. Release()
  389. {
  390. #asm
  391.     mov    ax,cs
  392.     sub    ax,0010h
  393.     mov    es,ax
  394.     mov    bx,ds
  395.     add    bx,1000h
  396.     sub    bx,ax
  397.     mov    ah,4Ah
  398.     int    21h
  399.     mov    ax,0
  400.     jnc    R_Rtn
  401.     inc    ax
  402. R_Rtn:
  403. #end
  404. }
  405.  
  406.  
  407. long Get_Vec(vector)
  408. unsigned vector ;
  409. {
  410. #asm
  411.     mov    ah,35h
  412.     mov    al,BYTE [bp+4]
  413.     int    21h
  414.     mov    ax,bx
  415.     mov    dx,es
  416. #end
  417. }
  418.  
  419.  
  420. Set_Vec(vector,addr)
  421. unsigned vector ;
  422. long addr ;
  423. {
  424. #asm
  425.     mov    ah,25h
  426.     mov    al,BYTE [bp+4]
  427.     mov    bx,WORD [bp+6]
  428.     mov    es,WORD [bp+8]
  429.     int    21h
  430. #end
  431. }
  432.  
  433.